/*
 * LDIR
 *
 * LDIR, a GPS cartography application built for Let's Do It Romania eco
 * campaign.
 * Copyright (C) 2010 Genera Software <office@generasoftware.com>
 *
 * http://generasoftware.com/
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 */
#include <aknviewappui.h>
#include <eikappui.h>
#include <aknview.h>
#include <LDIR.rsg>
#include "LDIRListCache.h"
#include "Settings.h"
#include "WasteCache.h"
#include "WasteInfo.h"
#include "LDIR.hrh"
#include "LDIRWaste.hrh"
#include "LDIRSettings.hrh"
#include "LDIRMain.hrh"
#include <aknlists.h>
#include <aknutils.h>
#include <akniconutils.h>
#include <akniconarray.h>
#include <AknsDrawUtils.h>
#include <gulicon.h>
#include <eikclbd.h>
#include <AknsBasicBackgroundControlContext.h>
#include <stringloader.h>
#include <LDIR.mbg>
_LIT(KListItemFormat, "%d\t%S\t%S\t");

/**
 * First phase of Symbian two-phase construction. Should not
 * contain any code that could leave.
 */
CLDIRListCache::CLDIRListCache()
	{
	}
/**
 * Destroy child controls.
 */
CLDIRListCache::~CLDIRListCache()
	{
	delete iBackground;
	}

/**
 * Construct the control (first phase).
 *  Creates an instance and initializes it.
 *  Instance is not left on cleanup stack.
 * @param aRect bounding rectangle
 * @param aParent owning parent, or NULL
 * @param aCommandObserver command observer
 * @return initialized instance of CLDIRListCache
 */
CLDIRListCache* CLDIRListCache::NewL( const TRect& aRect,
	const CCoeControl* aParent, MEikCommandObserver* aCommandObserver )
	{
	CLDIRListCache* self = CLDIRListCache::NewLC( aRect, aParent,
		aCommandObserver );
	CleanupStack::Pop( self );
	return self;
	}

/**
 * Construct the control (first phase).
 *  Creates an instance and initializes it.
 *  Instance is left on cleanup stack.
 * @param aRect The rectangle for this window
 * @param aParent owning parent, or NULL
 * @param aCommandObserver command observer
 * @return new instance of CLDIRListCache
 */
CLDIRListCache* CLDIRListCache::NewLC( const TRect& aRect,
	const CCoeControl* aParent, MEikCommandObserver* aCommandObserver )
	{
	CLDIRListCache* self = new ( ELeave ) CLDIRListCache();
	CleanupStack::PushL( self );
	self->ConstructL( aRect, aParent, aCommandObserver );
	return self;
	}

/**
 * Construct the control (second phase).
 *  Creates a window to contain the controls and activates it.
 * @param aRect bounding rectangle
 * @param aCommandObserver command observer
 * @param aParent owning parent, or NULL
 */
void CLDIRListCache::ConstructL( const TRect& aRect,
	const CCoeControl* aParent, MEikCommandObserver* aCommandObserver )
	{
	if ( aParent == NULL )
		{
		CreateWindowL();
		}
	else
		{
		SetContainerWindowL( *aParent );
		}
	iFocusControl = NULL;
	iCommandObserver = aCommandObserver;
	// support themes
	iBackground = CAknsBasicBackgroundControlContext::NewL(
		KAknsIIDQsnBgAreaMain, aRect, ETrue );
	InitializeControlsL();
	SetRect( aRect );
	ActivateL();
	}

/**
 *    Handle resizing of the container. This implementation will lay out
 *  full-sized controls like list boxes for any screen size, and will layout
 *  labels, editors, etc. to the size they were given in the UI designer.
 *  This code will need to be modified to adjust arbitrary controls to
 *  any screen size.
 */
void CLDIRListCache::SizeChanged()
	{
	CCoeControl::SizeChanged();
	if ( iBackground )
		{
		// support themes
		delete iBackground;
		iBackground = NULL;
		iBackground = CAknsBasicBackgroundControlContext::NewL(
			KAknsIIDQsnBgAreaMain, Rect(), EFalse );
		}
	LayoutControls();
	}

TTypeUid::Ptr CLDIRListCache::MopSupplyObject( TTypeUid aId )
	{
	// support themes
	return iBackground != NULL ? MAknsControlContext::SupplyMopObject( aId,
		iBackground ) : CCoeControl::MopSupplyObject( aId );
	}

void CLDIRListCache::HandleListBoxEventL( CEikListBox* aListBox,
	TListBoxEvent anEventType )
	{
	if ( EEventItemClicked == anEventType || EEventEnterKeyPressed
		== anEventType )
		{
		iCommandObserver->ProcessCommandL( ECmdEdit );
		}
	}

/**
 * Layout components as specified in the UI Designer
 */
void CLDIRListCache::LayoutControls()
	{
	if ( iListBox )
		iListBox->SetExtent( TPoint( 0, 0 ), Rect().Size() );

	}

/**
 *    Handle key events.
 */
TKeyResponse CLDIRListCache::OfferKeyEventL( const TKeyEvent& aKeyEvent,
	TEventCode aType )
	{
	if ( iFocusControl != NULL && iFocusControl->OfferKeyEventL( aKeyEvent,
		aType ) == EKeyWasConsumed )
		{
		return EKeyWasConsumed;
		}
	return CCoeControl::OfferKeyEventL( aKeyEvent, aType );
	}

/**
 *    Initialize each control upon creation.
 */
void CLDIRListCache::InitializeControlsL()
	{
	InitComponentArrayL();
	iListBox = new ( ELeave ) CAknDoubleLargeStyleListBox;
	Components().AppendLC( iListBox );
	CleanupStack::Pop( iListBox );
	iListBox->ConstructL( this, EAknListBoxSelectionList );
	iListBox->SetContainerWindowL( *this );
	iListBox->SetMopParent( this );
	iListBox->CreateScrollBarFrameL( ETrue );
	iListBox->ScrollBarFrame()->SetScrollBarVisibilityL(
		CEikScrollBarFrame::EOn, CEikScrollBarFrame::EAuto );
	iListBox->SetListBoxObserver( this );
	iFocusControl = iListBox;

	SetIconArrayL();
	CreateListEntriesL();
	}

/**
 * Handle global resource changes, such as scalable UI or skin events (override)
 */
void CLDIRListCache::HandleResourceChange( TInt aType )
	{
	CCoeControl::HandleResourceChange( aType );
	SetRect(
		iAvkonViewAppUi->View( TUid::Uid( ELDIRListCacheViewId ) )->ClientRect() );
	}

void CLDIRListCache::PrepareEditL()
	{
	TInt index = iListBox->CurrentItemIndex();
	CSettings& settings = CSettings::InstanceL();
	delete settings.WorkingWaste();
	settings.SetWorkingWaste( settings.PendingUploadCache()[index]->CloneL() );
	}

/**
 *    Draw container contents.
 */
void CLDIRListCache::Draw( const TRect& aRect ) const
	{
	CWindowGc& gc = SystemGc();
	gc.Clear( aRect );
	// draw theme background
	MAknsSkinInstance* skin = AknsUtils::SkinInstance();
	MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );
	AknsDrawUtils::Background( skin, cc, this, gc, aRect );
	}

void CLDIRListCache::SetIconArrayL()
	{
	CArrayPtr<CGulIcon>* iconList = new ( ELeave ) CAknIconArray( 2 );
	CleanupStack::PushL( iconList );

	CFbsBitmap* aBitmap;
	CFbsBitmap* aMask;
	CGulIcon* icon;
	TSize aSize;//I don't specify any custom size

	TFileName filename = CSettings::InstanceL().MifFile();

	AknIconUtils::CreateIconL( aBitmap, aMask, filename, EMbmLdirGarbage,
		EMbmLdirGarbage_mask );
	AknIconUtils::SetSize( aBitmap, aSize, EAspectRatioNotPreserved );

	icon = CGulIcon::NewL( aBitmap, aMask );
	CleanupStack::PushL( icon );
	icon->SetBitmapsOwnedExternally( EFalse );
	iconList->AppendL( icon );
	CleanupStack::Pop( icon );

	iListBox->ItemDrawer()->ColumnData()->SetIconArrayL( iconList );
	CleanupStack::Pop( iconList );
	}

void CLDIRListCache::CreateListEntriesL()
	{
	_LIT(KFormatDateTime,"%D%M%*Y%/0%1%/1%2%/2%3%/3 %:0%H%:1%T%:2%S.%C%:3");

	TBuf<128> entry;
	TBuf<32> datetime;
	CSettings& settings = CSettings::InstanceL();
	CWasteCache& pendingCache = settings.PendingUploadCache();
	TInt count = pendingCache.Count();
	if ( count )
		{
		CDesCArray* array = new ( ELeave ) CDesCArrayFlat( 4 );
		CleanupStack::PushL( array );

		for ( TInt i = 0; i < count; ++i )
			{
			CWasteInfo* wasteInfo = pendingCache[i];
			wasteInfo->iTime.FormatL( datetime, KFormatDateTime );

			entry.Format( KListItemFormat, 0, &datetime, &KNullDesC );
			array->AppendL( entry );
			}

		// add array to list
		iListBox->Model()->SetItemTextArray( array );
		iListBox->Model()->SetOwnershipType( ELbmOwnsItemArray );
		CleanupStack::Pop( array );
		iListBox->HandleItemAdditionL();
		}
	}

void CLDIRListCache::Delete()
	{
	TInt index = iListBox->CurrentItemIndex();
	CSettings& settings = CSettings::InstanceL();
	settings.PendingUploadCache().Remove( index );
	CDesCArray* array =
		static_cast<CDesCArray*> ( iListBox->Model()->ItemTextArray() );
	array->Delete( index );
	iListBox->HandleItemAdditionL();
	}

void CLDIRListCache::DeleteAll()
	{
	CSettings& settings = CSettings::InstanceL();
	settings.PendingUploadCache().ClearCache();
	CDesCArray* array = new ( ELeave ) CDesCArrayFlat( 4 );
	CleanupStack::PushL( array );
	iListBox->Model()->SetItemTextArray( array );
	CleanupStack::Pop( array );
	iListBox->HandleItemAdditionL();
	}
